//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#include <buola/python.h>

#include <buola/python/cthread.h>
#include <buola/python/types.h>

namespace buola { namespace python {

CThread::CThread(const YObject &pCode)
    :   mCode(pCode),
        mThreadState(nullptr)
{
}

CThread::~CThread()
{
}

void CThread::Start()
{
    mThread=new thread(std::bind(&CThread::Run,this));
}

void CThread::Run()
{
    python::CLock lPythonLock;

    mThreadState=PyThreadState_Get();
    YModule lMain=get_main_module();
    YDict lDict=lMain.GetDict();

    PyEval_EvalCode(mCode,lDict,lDict);
    if(PyErr_Occurred())
    {
        PyErr_Print();
        PyErr_Clear();
    }

    eThreadFinished();
    mThreadState=nullptr;
}

void CThread::RaiseInterrupt()
{
    if(mThreadState)
    {
        CCancelThread *lCancel=new CCancelThread(
                                        mThreadState->thread_id);
        lCancel->Start();
    }
}

CCancelThread::CCancelThread(long pVictim)
    :   mVictim(pVictim)
{
}

void CCancelThread::Start()
{
    mThread=new thread(std::bind(&CCancelThread::Run,this));
}

void CCancelThread::Run()
{
    python::CLock lLock;
    PyThreadState_SetAsyncExc(mVictim,PyExc_KeyboardInterrupt);
}

/*namespace python*/ } /*namespace buola*/ }
